package com.jweb.framework.http.interceptors;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.jweb.framework.core.ContextEx;
import com.jweb.framework.core.CoreException;
import com.jweb.framework.core.RuntimeSuperException;
import com.jweb.framework.core.channel.ChannelContext;
import com.jweb.framework.core.channel.interceptors.ExceptionHandler;
import com.jweb.framework.core.support.TRACER;
import com.jweb.framework.http.support.MimeTypes;
import com.jweb.framework.http.support.Utils;

/**
 * 修改人： Thomas
 * 修改内容：新增 
 * 类说明：对Form表单请求及响应的处理
 */
public class FormPayloadChannelInterceptor<Request,Response> implements ServletChannelInterceptor<Request,Response> {
	private static Logger logger = LoggerFactory.getLogger(FormPayloadChannelInterceptor.class);
	private final MimeTypes mimeTypes = new MimeTypes();
	private String contentType ;
	private String encoding ;
	private boolean extractIdentityFromURI = true ;
	private ExceptionHandler exceptionHandler ;
	
	public void setExceptionHandler(ExceptionHandler exceptionHandler){
		this.exceptionHandler = exceptionHandler ;
	}
	
	public void setExtractIdentityFromURI(boolean flag){
		this.extractIdentityFromURI = flag ;
	}
	
	public void setContentType(String contentType){
		this.contentType = contentType ;
	}
	
	public void setEncoding(String encoding){
		this.encoding = encoding ;
	}
	
	@Override
	public void onRequest(ChannelContext<Request, Response> channelContext,
			ContextEx contextEx) throws CoreException {
		HttpServletRequest request = (HttpServletRequest) channelContext.getRequest() ;
		if(this.extractIdentityFromURI){ // true
			String processId = Utils.getIdentity(request);// processId="fileUpload"
			contextEx.setProcessId(processId);
		}
		
		Object obj = new HashMap(request.getParameterMap()); // obj={UPLOAD_SUBDIRS=[Ljava.lang.String;@533c533c, name=[Ljava.lang.String;@534d534d}
		
		String str = Utils.getRefererResolver(request).resolveReferer(request, (Map)obj); // str=null
		if(logger.isDebugEnabled() && str!=null){
			logger.debug("referer: " + str);
		}
		
		HashMap hashMap = new HashMap();
		
		for(Iterator it = ((Map)obj).entrySet().iterator() ; it.hasNext() ;){
			Map.Entry entry = (Entry) it.next();
			parseRequest((String)entry.getKey() , (String[])entry.getValue() , hashMap); // 对上送上来的参数进行处理，并放入至hashMap中。
		}
		parseRequest(hashMap); // 
		
		if(request instanceof MultipartHttpServletRequest){
			Map<String , MultipartFile> fileMap = ((MultipartHttpServletRequest) request).getFileMap() ;
			hashMap.putAll(fileMap) ;
		}
		
		channelContext.setRequestPayload(hashMap);
		
	}
	
private boolean parseRequest(Map hashMap) {
		
		boolean flag = true ;
		for(Iterator it = hashMap.entrySet().iterator() ; it.hasNext() ;){
			Map.Entry entry = (Entry) it.next();
			if(entry.getValue() instanceof List){
				for(Iterator it2 = ((List)entry.getValue()).iterator() ; it2.hasNext() ;){
					Map map = (Map) it2.next();
					if(parseRequest(map)){
						// it2.remove(); 集合对象的值不删除。
					}
				}
			}
			else if((((String)entry.getKey()).charAt(0)=='$')){
				flag = false ;
			}
		}
		
		return flag ;
	}

	private void parseRequest(String str, String[] value, Map hashMap) {
		
		int i = str.indexOf(".");
		Object obj2 ; 
		if(i!=-1){
			String str1 = str.substring(0, i);
			String str2 = str.substring(i+1);
			
			int l = str1.indexOf('[');
			if(l != -1){
				int i1 = str1.indexOf(']',l);
				if(i1==-1 || i1 != str1.length()-1){
					throw new IllegalArgumentException("no ']' found for '[' or ']' is not end of name .");
				}
				obj2 = str1.substring(0, l);
				int i3 = Integer.parseInt(str1.substring(l+1 , i1));
				Map map = parseRequest(hashMap, (String)obj2 , i3);
				parseRequest(str2 , value , map);
			}
			else {
				Object obj1 = hashMap.get(str1);
				if(obj1 == null){
					obj1 = new HashMap();
					hashMap.put(str1, obj1);
				}
				parseRequest(str2 , value , (Map) obj1);
			}
		}
		else {
			int j = str.indexOf('[');
			/*if(j != -1){
				int k = str.indexOf(']',j);
				if((k==-1) || (k!=str.length()-1)){
					throw new IllegalArgumentException("no ']' found for '[' or ']' is not end of name . ");
				}
				String str3 = str.substring(0 , j);
				int i2 = Integer.parseInt(str.substring(j+1, k));
				obj2 = parseRequest(hashMap , str3 , i2);
				parseRequest(str , value , (Map)obj2);
			}*/
			//else {  // true
				parseRequestB(str , value , hashMap);
			//}
		}
		
		
	}

	private Map<String, Object> parseRequest(Map hashMap, String str, int index) {
		
		Object obj = (List)hashMap.get(str);
		if(obj == null){
			obj = new ArrayList();
			hashMap.put(str, obj);
		}
		if(((List)obj).size()<=index){
			for(int i=((List)obj).size() ; i<=index ; i++){
				((List)obj).add(new HashMap());
			}
		}
		
		return (Map<String, Object>) ((List)obj).get(index) ;
	}

	private void parseRequestB(String str, String[] value, Map hashMap) {
		
		Object obj = null ;
		if(value!=null && value.length>0){
			if(value.length == 1){
				obj = value[0] ;
			}
			else {
				obj = value ;
			}
		}
		hashMap.put(str, obj);
	}

	@Override
	public void onResponse(ChannelContext<Request, Response> channelContext,
			ContextEx ctxEx, Throwable throwable) {
		if((channelContext.getResponsePalyload() instanceof byte[]) && ctxEx.getData("excelStream")!=null){
			byte[] bytes = (byte[])channelContext.getResponsePalyload();
			try{
				HttpServletResponse response = (HttpServletResponse) channelContext.getResponse();
				/*response.setContentLength(bytes.length);
				response.setLocale(contextEx.getLocale());
				if(this.encoding != null){
					response.setCharacterEncoding(this.encoding);
				}
				response.getOutputStream().write(bytes);
				response.getOutputStream().flush();*/
				// 清空response
				response.reset();
				// 设置response的Header
				response.addHeader("Content-Disposition",
						"attachment;filename=" + new String((ctxEx.getData("fileName")+".xls").getBytes("GB2312"), "ISO8859-1"));
				response.setContentType("application/vnd.ms-excel;charset=gb2312");
				response.getOutputStream().write(bytes);
				response.getOutputStream().flush();
			}
			catch (IOException e){
				TRACER.trace("write http stream error" , e);
			}
		}
		else if((channelContext.getResponsePalyload() instanceof byte[]) && ctxEx.getData("outputStream")!=null){
			byte[] bytes = (byte[])channelContext.getResponsePalyload();
			try{
				HttpServletResponse response = (HttpServletResponse) channelContext.getResponse();
				response.setContentLength(bytes.length);
				response.setLocale(ctxEx.getLocale());
				if(this.encoding != null){
					response.setCharacterEncoding(this.encoding);
				}
				response.getOutputStream().write(bytes);
				response.getOutputStream().flush();
				
			}
			catch (IOException e){
				TRACER.trace("write http stream error" , e);
			}
		}
		else if(channelContext.getResponsePalyload() instanceof byte[]){
			byte[] bytes = (byte[])channelContext.getResponsePalyload();
			try{
				HttpServletResponse response = (HttpServletResponse) channelContext.getResponse();
				if(this.contentType != null){
					response.setContentType(this.contentType);
				}
				else {
					List list = this.mimeTypes.getMediaTypes((HttpServletRequest) channelContext.getRequest());
					if(!list.isEmpty()){
						response.setContentType(MediaType.toString(list));
					}
				}
				response.setContentLength(bytes.length);
				response.setLocale(ctxEx.getLocale());
				if(this.encoding != null){
					response.setCharacterEncoding(this.encoding);
				}
				response.getOutputStream().write(bytes);
				response.getOutputStream().flush();
				
			}
			catch (IOException e){
				TRACER.trace("write http stream error" , e);
			}
		}
		else if(throwable!=null || ctxEx.getException()!=null){
			if(throwable == null){
				throwable = ctxEx.getException();
				if(this.exceptionHandler != null){
					this.exceptionHandler.handleException(throwable , ctxEx);
					channelContext.setResponsePayload(ctxEx.getDataMap());
				}
				throw new RuntimeSuperException("JAVAHT0002" , throwable.getMessage() , throwable);
			}
			if(this.exceptionHandler!=null){
				this.exceptionHandler.handleException(throwable, ctxEx);
				channelContext.setResponsePayload(ctxEx.getDataMap());
			}
		}
		else {
			Utils.getRefererResolver((HttpServletRequest) channelContext.getRequest()).setReferer((HttpServletRequest) channelContext.getRequest());
		}
		
	}

	
}
